Add OpenAPI docs for Sourcebot public API#996
Add OpenAPI docs for Sourcebot public API#996brendan-kellam merged 6 commits intosourcebot-dev:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds generated OpenAPI docs and generation tooling for Sourcebot's public REST surface; centralizes git-related Zod schemas; exposes the spec via a new API route; integrates generation into CI/release and copies the spec into the Docker image. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor CI as CI/Release Job
participant Gen as generateOpenApi.ts
participant FS as Repository FS
participant Git as Git Commit Step
participant Runner as Web App (server)
participant Client as Browser / Doc Consumer
CI->>Gen: run yarn openapi:generate
Gen->>FS: create docs/api-reference/...json
FS-->>Gen: write success
CI->>Git: stage & commit generated spec
Git-->>CI: commit success
Runner->>FS: read docs/api-reference/...json (openapi.json route)
Client->>Runner: GET /api/openapi.json
Runner-->>Client: application/vnd.oai.openapi+json document
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Generate and publish OpenAPI docs for the public search, repo, and file-browsing endpoints, add Mintlify integration, and serve the generated spec at /api/openapi.json. Note: /api/stream_search remains modeled as text/event-stream in OpenAPI. OpenAPI 3.0 does not provide a first-class way to describe SSE frames as a typed stream of JSON events.
872c4d8 to
17a49a9
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
packages/web/src/openapi/publicApiDocument.ts (2)
232-238: Consider adding additional server entries for production/cloud environments.The servers array only includes the local development server. For a public API reference, consumers might benefit from seeing the production URL pattern or a placeholder indicating where to substitute their deployment URL.
📝 Suggested enhancement
servers: [ { url: 'http://localhost:3000', description: 'Local development web app', }, + { + url: 'https://{your-domain}', + description: 'Your Sourcebot deployment', + }, ],🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/openapi/publicApiDocument.ts` around lines 232 - 238, The OpenAPI document's servers array currently only lists the local entry; update the servers array in publicApiDocument to include additional entries for production/cloud (e.g., a production URL and a templated/placeholder like {baseUrl}) so consumers see expected deployment endpoints. Modify the servers array where it's defined (the variable/object containing servers and tags: [searchTag, reposTag, filesTag, miscTag]) to add a production URL and/or a URL template with a description and optional variables (e.g., baseUrl) so clients can substitute their environment; ensure descriptions clearly label development vs production entries.
24-46: Consider adding a comment explaining the manual schema definition.The manual
SchemaObjectdefinitions for the file tree node are necessary becausezod-to-openapidoesn't handle recursive/self-referential schemas well. A brief inline comment would help future maintainers understand why these aren't derived from Zod schemas like the other definitions.📝 Suggested documentation
+// Manual OpenAPI schema for the recursive file tree node structure. +// zod-to-openapi doesn't support z.lazy() / self-referential schemas, +// so we define this directly as a SchemaObject with $ref. const publicFileTreeNodeSchema: SchemaObject = { type: 'object',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/openapi/publicApiDocument.ts` around lines 24 - 46, Add a short inline comment above the manual SchemaObject definitions explaining why they are hand-written: publicFileTreeNodeSchema (recursive/self-referential children) and publicGetTreeResponseSchema cannot be generated from the Zod types because zod-to-openapi does not handle recursive schemas; state that this is intentional and link or note zod-to-openapi's limitation to aid future maintainers.packages/web/src/openapi/publicApiSchemas.ts (1)
18-23: The current Zod extension pattern is safe and reasonable.The guard at lines 18-23 is an appropriate approach since
extendZodWithOpenApiis only called in this file. While moving the extension to a dedicated initialization module could be a minor structural improvement, it is not necessary for correctness and the current implementation prevents accidental double-extension within the module's execution context.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/openapi/publicApiSchemas.ts` around lines 18 - 23, Keep the current safe pattern: leave the module-scoped guard (hasExtendedZod) and the call to extendZodWithOpenApi(z) as-is so the Zod extension runs exactly once within this module; ensure you don't remove hasExtendedZod or introduce another extension call elsewhere (refer to hasExtendedZod, extendZodWithOpenApi, and z) — if you prefer a refactor later, move the same guarded logic into a dedicated initialization module, but no functional change is needed now.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/api-reference/sourcebot-public.openapi.json`:
- Around line 8-13: The OpenAPI document currently exposes a local-only server
("servers" -> url "http://localhost:3000"), which will be embedded into
generated clients; update the "servers" entry in the API spec by either removing
the entire "servers" array or replacing the localhost URL with a deploy-safe
default (e.g., a production or placeholder base URL such as
"https://api.example.com" or a templated variable) so generated clients/tooling
don't default to localhost; ensure you modify the "servers" array in the
top-level OpenAPI object to reflect this change.
- Around line 444-448: The description of the PublicStreamSearchSse type
references a missing schema PublicStreamedSearchEvent in components.schemas;
either add a proper schema definition for PublicStreamedSearchEvent (and any
sub-event variants like "chunk"/"done" you expect) into the source OpenAPI model
so components.schemas.PublicStreamedSearchEvent exists and describes the SSE
JSON frame shape, and ensure the generator/template picks up that schema, or
remove/replace the dangling name from PublicStreamSearchSse.description in the
source document so it does not reference a non-existent schema; update the
source generator templates if necessary so generated docs include
components.schemas.PublicStreamedSearchEvent.
In `@docs/docs/api-reference/overview.mdx`:
- Around line 6-8: Rewrite the opening paragraph so it leads with the runtime
spec URL "/api/openapi.json" (instead of the static docs artifact
"/api-reference/sourcebot-public.openapi.json"), use second person ("you") and
present tense, and keep sentences short and direct; specifically update the
lines that currently say "Sourcebot exposes a public REST API..." and the
sentence mentioning the Mintlify-rendered file so they start by telling the
reader to use "/api/openapi.json" on their instance, and state that the endpoint
reference is generated from Zod schemas/OpenAPI registry and rendered by
Mintlify in plain, actionable language.
---
Nitpick comments:
In `@packages/web/src/openapi/publicApiDocument.ts`:
- Around line 232-238: The OpenAPI document's servers array currently only lists
the local entry; update the servers array in publicApiDocument to include
additional entries for production/cloud (e.g., a production URL and a
templated/placeholder like {baseUrl}) so consumers see expected deployment
endpoints. Modify the servers array where it's defined (the variable/object
containing servers and tags: [searchTag, reposTag, filesTag, miscTag]) to add a
production URL and/or a URL template with a description and optional variables
(e.g., baseUrl) so clients can substitute their environment; ensure descriptions
clearly label development vs production entries.
- Around line 24-46: Add a short inline comment above the manual SchemaObject
definitions explaining why they are hand-written: publicFileTreeNodeSchema
(recursive/self-referential children) and publicGetTreeResponseSchema cannot be
generated from the Zod types because zod-to-openapi does not handle recursive
schemas; state that this is intentional and link or note zod-to-openapi's
limitation to aid future maintainers.
In `@packages/web/src/openapi/publicApiSchemas.ts`:
- Around line 18-23: Keep the current safe pattern: leave the module-scoped
guard (hasExtendedZod) and the call to extendZodWithOpenApi(z) as-is so the Zod
extension runs exactly once within this module; ensure you don't remove
hasExtendedZod or introduce another extension call elsewhere (refer to
hasExtendedZod, extendZodWithOpenApi, and z) — if you prefer a refactor later,
move the same guarded logic into a dedicated initialization module, but no
functional change is needed now.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2c747ce7-d9a5-4fe6-acc2-6c9ca546f4ed
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (15)
docs/api-reference/sourcebot-public.openapi.jsondocs/docs.jsondocs/docs/api-reference/overview.mdxpackage.jsonpackages/backend/src/api.tspackages/web/package.jsonpackages/web/src/app/api/(server)/openapi.json/route.tspackages/web/src/app/api/(server)/source/route.tspackages/web/src/features/git/getFileSourceApi.tspackages/web/src/features/git/getFilesApi.tspackages/web/src/features/git/getTreeApi.tspackages/web/src/features/git/schemas.tspackages/web/src/openapi/publicApiDocument.tspackages/web/src/openapi/publicApiSchemas.tspackages/web/tools/generateOpenApi.ts
Remove the localhost servers entry, clarify the SSE stream description, point docs readers at /api/openapi.json, add the changelog entry, and update the lockfile metadata.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@CHANGELOG.md`:
- Around line 10-13: Update the changelog entry that currently reads "Added
generated OpenAPI documentation for the public search, repo, and file browsing
API surface. [`#101`]" to use the correct pull request id "[`#996`]" and move this
line from the "### Changed" section into the "### Added" section; ensure the
entry ends with " [`#996`]" and that the "### Added" header contains this line
while removing it from "### Changed".
In `@packages/web/src/openapi/publicApiDocument.ts`:
- Around line 225-239: The OpenAPI document currently lacks security
definitions; after generator.generateDocument(...) add a securitySchemes entry
under document.components (e.g., document.components.securitySchemes = {
bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' } }) and set a
global document.security (e.g., document.security = [{ bearerAuth: [] }]) so
clients know to send credentials; keep per-operation overrides (clear security
on truly unauthenticated endpoints) rather than leaving endpoints anonymous. Use
the existing symbols document, document.components, and
generator.generateDocument to locate where to add these fields and add/merge
them alongside the existing schemas logic that sets document.components.schemas
and PublicFileTreeNode.
In `@packages/web/src/openapi/publicApiSchemas.ts`:
- Around line 41-46: publicVersionResponseSchema currently pins the example for
the version field to a hard-coded string which drifts from the actual build;
update the z.object for publicVersionResponseSchema so the version example is
either removed or set dynamically (e.g., use the app/build version constant)
instead of the literal 'v4.15.2' — locate publicVersionResponseSchema and the
nested version field in publicApiSchemas.ts and replace the static example with
a dynamic value pulled from your build/version export or drop the example
entirely.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: dafa7a08-28f4-4294-8e43-f8d4e07c8a8c
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (5)
CHANGELOG.mddocs/api-reference/sourcebot-public.openapi.jsondocs/docs/api-reference/overview.mdxpackages/web/src/openapi/publicApiDocument.tspackages/web/src/openapi/publicApiSchemas.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- docs/docs/api-reference/overview.mdx
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/release-prod.yml:
- Around line 134-138: The workflow runs "Install dependencies" and "Generate
OpenAPI docs" while the repo remote has the write-scoped GitHub App token
persisted; change the checkout/credential handling so these steps run without
persisted credentials: set the actions/checkout used before the "Install
dependencies" and "Generate OpenAPI docs" steps to persist-credentials: false
(or use a read-only checkout action), and only configure/inject the write-scoped
app token immediately before the step that performs the git push (e.g., the step
that calls git push or "Release" logic). Ensure the checkout used for the push
step has persist-credentials true or re-checkout with the token injected so only
the final push runs with write access.
In `@docs/api-reference/sourcebot-public.openapi.json`:
- Around line 141-148: Change discrete numeric schema types from "number" to
"integer" for fields representing counts/IDs/positions—specifically update
"byteOffset", "lineNumber", and "column" (and other discrete fields like IDs,
status codes, pagination/count fields) to use "type": "integer" and add
"format": "int32" or "int64" where appropriate in the OpenAPI generator output;
update the generator/template that emits these properties so all occurrences
(e.g., other count/id/position schemas referenced in the spec) are emitted as
integer types rather than floating-point numbers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7980c617-35d4-4c3e-897c-c8c8f9dde470
📒 Files selected for processing (2)
.github/workflows/release-prod.ymldocs/api-reference/sourcebot-public.openapi.json
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/web/src/app/api/(server)/openapi.json/route.ts (1)
18-26: Add explicit GET query validation for this API route.This GET handler does not validate query params with a Zod schema +
queryParamsSchemaValidationError. Even if no params are expected, validate an explicit empty schema to enforce contract consistency.As per coding guidelines
API route handlers should validate query parameters using Zod schemas with queryParamsSchemaValidationError for GET requests.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/web/src/app/api/`(server)/openapi.json/route.ts around lines 18 - 26, Add explicit query validation at the top of the exported GET handler: create a Zod empty object schema (e.g., const querySchema = z.object({})) and validate the incoming request query against it before calling loadOpenApiDocument(); on validation failure return the existing queryParamsSchemaValidationError with the Zod error. Import z from 'zod' and queryParamsSchemaValidationError, perform the parse/parseAsync on the request's query/searchParams inside the async function exported as GET (the handler passed to apiHandler), and only proceed to call loadOpenApiDocument() and return Response.json(...) when validation succeeds.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/web/src/app/api/`(server)/openapi.json/route.ts:
- Around line 8-15: Resolve the OpenAPI file path from process.cwd() into the
container's /app docs (use path.join(process.cwd(), 'docs', 'api-reference',
'sourcebot-public.openapi.json') instead of '../../docs/...') when constructing
openApiPath, and change the ENOENT catch branch in the JSON read/parse block
(the JSON.parse(await fs.readFile(...)) try/catch around openApiPath) to not
silently swallow the error: either rethrow or throw a new explicit error (e.g.,
"OpenAPI document not found") so the handler returns an error/404 instead of a
successful empty response; apply the same path and ENOENT handling fix to the
analogous block referenced at lines 19-25.
---
Nitpick comments:
In `@packages/web/src/app/api/`(server)/openapi.json/route.ts:
- Around line 18-26: Add explicit query validation at the top of the exported
GET handler: create a Zod empty object schema (e.g., const querySchema =
z.object({})) and validate the incoming request query against it before calling
loadOpenApiDocument(); on validation failure return the existing
queryParamsSchemaValidationError with the Zod error. Import z from 'zod' and
queryParamsSchemaValidationError, perform the parse/parseAsync on the request's
query/searchParams inside the async function exported as GET (the handler passed
to apiHandler), and only proceed to call loadOpenApiDocument() and return
Response.json(...) when validation succeeds.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b9b71832-ee78-4799-9314-a0c36d030598
📒 Files selected for processing (2)
Dockerfilepackages/web/src/app/api/(server)/openapi.json/route.ts
Generate and publish OpenAPI docs for the public search, repo, and file-browsing endpoints, add Mintlify integration, and serve the generated spec at /api/openapi.json.
Note: /api/stream_search remains modeled as text/event-stream in OpenAPI. OpenAPI 3.0 does not provide a first-class way to describe SSE frames as a typed stream of JSON events.
Fixes #101
Summary by CodeRabbit
Documentation
New Features
Chores